#include "aht20.h"
#include "driver/i2c.h"
#include "esp_log.h"

static const char *TAG = "AHT20";
static bool i2c_initialized = false;

// 前置声明静态函数
static esp_err_t aht20_i2c_init(void);
static esp_err_t aht20_send_cmd(uint8_t cmd, uint8_t param1, uint8_t param2);
static esp_err_t aht20_read_data(uint8_t *data, size_t len);
static esp_err_t aht20_read_byte(uint8_t reg, uint8_t *data);
static esp_err_t aht20_read_data_reg(uint8_t reg, uint8_t *data, size_t len);

/**
 * @brief 初始化I2C总线（仅初始化一次）
 * 
 * @return esp_err_t 成功返回ESP_OK，失败返回相应错误码
 */
static esp_err_t aht20_i2c_init(void)
{
    if (i2c_initialized) {
        return ESP_OK;
    }
    
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };
    
    esp_err_t err = i2c_param_config(I2C_MASTER_NUM, &conf);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "I2C param config failed: %s", esp_err_to_name(err));
        return err;
    }
    
    err = i2c_driver_install(I2C_MASTER_NUM, conf.mode,
                              I2C_MASTER_RX_BUF_DISABLE,
                              I2C_MASTER_TX_BUF_DISABLE, 0);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "I2C driver install failed: %s", esp_err_to_name(err));
        return err;
    }
    
    i2c_initialized = true;
    ESP_LOGI(TAG, "I2C initialized successfully on SDA=%d, SCL=%d", 
             I2C_MASTER_SDA_IO, I2C_MASTER_SCL_IO);
    
    return ESP_OK;
}

/**
 * @brief 初始化AHT20传感器及I2C总线
 * 
 * @return esp_err_t 成功返回ESP_OK，失败返回相应错误码
 */
esp_err_t aht20_init(void)
{
    esp_err_t err;
    
    // 初始化I2C总线
    err = aht20_i2c_init();
    if (err != ESP_OK) {
        return err;
    }
    
    // 等待传感器稳定
    vTaskDelay(pdMS_TO_TICKS(100));
    
    // 检查传感器是否存在
    uint8_t dummy_data;
    err = aht20_read_byte(0x00, &dummy_data);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "AHT20 sensor not found on I2C bus");
        return err;
    }
    
    ESP_LOGI(TAG, "AHT20 sensor initialized successfully");
    return ESP_OK;
}

/**
 * @brief 向AHT20传感器发送命令（带重试机制）
 * 
 * @param cmd 命令字节
 * @param param1 参数1
 * @param param2 参数2
 * @return esp_err_t 成功返回ESP_OK，失败返回相应错误码
 */
static esp_err_t aht20_send_cmd(uint8_t cmd, uint8_t param1, uint8_t param2)
{
    esp_err_t err;
    
    for (int i = 0; i < AHT20_INIT_RETRY_COUNT; i++) {
        i2c_cmd_handle_t cmd_handle = i2c_cmd_link_create();
        
        i2c_master_start(cmd_handle);
        i2c_master_write_byte(cmd_handle, (AHT20_ADDR_DEFAULT << 1) | I2C_MASTER_WRITE, true);
        i2c_master_write_byte(cmd_handle, cmd, true);
        i2c_master_write_byte(cmd_handle, param1, true);
        i2c_master_write_byte(cmd_handle, param2, true);
        i2c_master_stop(cmd_handle);
        
        err = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd_handle, 1000 / portTICK_PERIOD_MS);
        i2c_cmd_link_delete(cmd_handle);
        
        if (err == ESP_OK) {
            return ESP_OK;
        }
        
        ESP_LOGW(TAG, "Send cmd attempt %d failed: %s", i+1, esp_err_to_name(err));
        vTaskDelay(pdMS_TO_TICKS(10)); // 短暂延迟后重试
    }
    
    ESP_LOGE(TAG, "Send measure cmd failed after %d attempts: %s", 
             AHT20_INIT_RETRY_COUNT, esp_err_to_name(err));
    return err;
}

/**
 * @brief 从AHT20传感器读取数据（带重试机制）
 * 
 * @param data 存储读取数据的缓冲区
 * @param len 数据长度
 * @return esp_err_t 成功返回ESP_OK，失败返回相应错误码
 */
static esp_err_t aht20_read_data(uint8_t *data, size_t len)
{
    esp_err_t err;
    
    for (int i = 0; i < AHT20_READ_RETRY_COUNT; i++) {
        i2c_cmd_handle_t cmd_handle = i2c_cmd_link_create();
        
        i2c_master_start(cmd_handle);
        i2c_master_write_byte(cmd_handle, (AHT20_ADDR_DEFAULT << 1) | I2C_MASTER_READ, true);
        
        if (len > 1) {
            i2c_master_read(cmd_handle, data, len - 1, I2C_MASTER_ACK);
        }
        i2c_master_read_byte(cmd_handle, data + len - 1, I2C_MASTER_NACK);
        
        i2c_master_stop(cmd_handle);
        
        err = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd_handle, 1000 / portTICK_PERIOD_MS);
        i2c_cmd_link_delete(cmd_handle);
        
        if (err == ESP_OK) {
            return ESP_OK;
        }
        
        ESP_LOGW(TAG, "Read data attempt %d failed: %s", i+1, esp_err_to_name(err));
        vTaskDelay(pdMS_TO_TICKS(10)); // 短暂延迟后重试
    }
    
    ESP_LOGE(TAG, "Read measurement data failed after %d attempts: %s", 
             AHT20_READ_RETRY_COUNT, esp_err_to_name(err));
    return err;
}

/**
 * @brief 从AHT20传感器读取单个字节
 * 
 * @param reg 寄存器地址
 * @param data 存储读取数据的指针
 * @return esp_err_t 成功返回ESP_OK，失败返回相应错误码
 */
static esp_err_t aht20_read_byte(uint8_t reg, uint8_t *data)
{
    return aht20_read_data_reg(reg, data, 1);
}

/**
 * @brief 从AHT20传感器读取指定寄存器的数据
 * 
 * @param reg 寄存器地址
 * @param data 存储读取数据的缓冲区
 * @param len 数据长度
 * @return esp_err_t 成功返回ESP_OK，失败返回相应错误码
 */
static esp_err_t aht20_read_data_reg(uint8_t reg, uint8_t *data, size_t len)
{
    esp_err_t err;
    
    for (int i = 0; i < AHT20_READ_RETRY_COUNT; i++) {
        i2c_cmd_handle_t cmd_handle = i2c_cmd_link_create();
        
        // 写入寄存器地址
        i2c_master_start(cmd_handle);
        i2c_master_write_byte(cmd_handle, (AHT20_ADDR_DEFAULT << 1) | I2C_MASTER_WRITE, true);
        i2c_master_write_byte(cmd_handle, reg, true);
        
        // 读取数据
        i2c_master_start(cmd_handle);
        i2c_master_write_byte(cmd_handle, (AHT20_ADDR_DEFAULT << 1) | I2C_MASTER_READ, true);
        
        if (len > 1) {
            i2c_master_read(cmd_handle, data, len - 1, I2C_MASTER_ACK);
        }
        i2c_master_read_byte(cmd_handle, data + len - 1, I2C_MASTER_NACK);
        
        i2c_master_stop(cmd_handle);
        
        err = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd_handle, 1000 / portTICK_PERIOD_MS);
        i2c_cmd_link_delete(cmd_handle);
        
        if (err == ESP_OK) {
            return ESP_OK;
        }
        
        ESP_LOGW(TAG, "Read reg attempt %d failed: %s", i+1, esp_err_to_name(err));
        vTaskDelay(pdMS_TO_TICKS(10));
    }
    
    return err;
}

/**
 * @brief 读取传感器的湿度和温度值（带重试和错误处理）
 * 
 * @param v 指向aht20_sensor_value_t结构体的指针，用于存储读取的数据
 * @return int 成功返回1，失败返回0
 */
int aht20_read(aht20_sensor_value_t *v)
{
    uint8_t data[6];
    esp_err_t err;
    
    if (v == NULL) {
        ESP_LOGE(TAG, "Invalid pointer");
        return 0;
    }
    
    for (int retry = 0; retry < AHT20_READ_RETRY_COUNT; retry++) {
        // 发送测量命令
        err = aht20_send_cmd(0xAC, 0x33, 0x00);
        if (err != ESP_OK) {
            ESP_LOGW(TAG, "Failed to send measurement command (attempt %d): %s", 
                     retry + 1, esp_err_to_name(err));
            continue;
        }
        
        // 等待测量完成（最大80ms）
        vTaskDelay(80 / portTICK_PERIOD_MS);
        
        // 读取6字节数据
        err = aht20_read_data(data, 6);
        if (err != ESP_OK) {
            ESP_LOGW(TAG, "Failed to read measurement data (attempt %d): %s", 
                     retry + 1, esp_err_to_name(err));
            continue;
        }
        
        // 检查状态位
        if (data[0] & 0x80) {
            ESP_LOGW(TAG, "Sensor is busy (attempt %d)", retry + 1);
            vTaskDelay(20 / portTICK_PERIOD_MS); // 等待更长时间
            continue;
        }
        
        // 解析温湿度数据
        uint32_t humidity_raw = ((uint32_t)data[1] << 12) | ((uint32_t)data[2] << 4) | (data[3] >> 4);
        uint32_t temperature_raw = (((uint32_t)data[3] & 0x0F) << 16) | ((uint32_t)data[4] << 8) | data[5];
        
        // 转换为实际值
        float humidity = (humidity_raw * 100.0f) / 1048576.0f; // 2^20 = 1048576
        float temperature = (temperature_raw * 200.0f) / 1048576.0f - 50.0f;
        
        // 数据有效性检查
        if (humidity < 0 || humidity > 100 || temperature < -40 || temperature > 85) {
            ESP_LOGW(TAG, "Invalid sensor data (attempt %d): humidity=%.1f%%, temperature=%.1f°C", 
                     retry + 1, humidity, temperature);
            continue;
        }
        
        // 所有检查通过，保存数据
        v->humidity = humidity;
        v->temperature = temperature;
        
        ESP_LOGI(TAG, "Read successful: humidity=%.1f%%, temperature=%.1f°C", 
                 v->humidity, v->temperature);
        
        return 1;
    }
    
    ESP_LOGE(TAG, "Failed to read AHT20 sensor data after %d attempts", AHT20_READ_RETRY_COUNT);
    return 0;
}

/**
 * @brief 重置AHT20传感器
 * 
 * @return esp_err_t 成功返回ESP_OK，失败返回相应错误码
 */
esp_err_t aht20_reset(void)
{
    ESP_LOGI(TAG, "Resetting AHT20 sensor...");
    
    esp_err_t err = aht20_send_cmd(0xBA, 0x00, 0x00);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Reset command failed: %s", esp_err_to_name(err));
        return err;
    }
    
    // 等待重置完成
    vTaskDelay(pdMS_TO_TICKS(20));
    
    ESP_LOGI(TAG, "AHT20 sensor reset completed");
    return ESP_OK;
}

/**
 * @brief 获取AHT20传感器状态
 * 
 * @param status 存储状态信息的指针
 * @return esp_err_t 成功返回ESP_OK，失败返回相应错误码
 */
esp_err_t aht20_get_status(uint8_t *status)
{
    if (status == NULL) {
        return ESP_ERR_INVALID_ARG;
    }
    
    return aht20_read_byte(0x00, status);
}